﻿/*
 * Copyright (c) 2020-2025, Qingdao Digital Intelligent Ship & Ocean Technology Co., Ltd.
 * All rights reserved.
 *
 * This file is part of FastCAE and is distributed under the terms of the
 * BSD 3-Clause License. See the LICENSE file in the project root for details.
 */

#include "FITKOCCComandCommon.h"
#include <BRepBuilderAPI_MakeWire.hxx>
#include <ShapeFix_Wire.hxx>
#include <BRepBndLib.hxx>
#include <Bnd_Box.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <ShapeAnalysis.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <ShapeFix_Shape.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <IntTools_FClass2d.hxx>
#include <Geom_Plane.hxx>
#include <ShapeAnalysis_Surface.hxx>
#include <BRep_Tool.hxx>
#include <BRep_Builder.hxx>
#include <vector>
#include <algorithm>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <BRepTools_ReShape.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include "FITKOCCModelRefine.h"
#include <QDebug> 
#include <Geom_TrimmedCurve.hxx>
#include <GeomConvert.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GCPnts_UniformAbscissa.hxx>
#include <CPnts_AbscissaPoint.hxx>
#include <BRepGProp.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <TopTools_HSequenceOfShape.hxx>
#include <ShapeAnalysis_FreeBounds.hxx>
#include <TopoDS_Builder.hxx>

namespace OCC
{
    void FITKOCCComandCommon::FlattenCompShape(const TopoDS_Shape & shape, QList<TopoDS_Shape> & shapes)
    {
        if (shape.IsNull())
        {
            return;
        }

        TopAbs_ShapeEnum sType = shape.ShapeType();
        switch (sType)
        {
        case TopAbs_COMPOUND:
        case TopAbs_COMPSOLID:
        {
            // 遍历子形状。
            TopoDS_Iterator iter(shape);
            for (; iter.More(); iter.Next())
            {
                // 获取子形状递归拆分形状及信息。
                const TopoDS_Shape & subShape = iter.Value();
                FlattenCompShape(subShape, shapes);
            }

            break;
        }
        case TopAbs_SOLID:
        case TopAbs_SHELL:
        case TopAbs_FACE:
        case TopAbs_WIRE:
        case TopAbs_EDGE:
        case TopAbs_VERTEX:
        {
            shapes.push_back(shape);
            break;
        }
        default:
            break;
        }
    }

    void FITKOCCComandCommon::FlattenCompShape2D(const TopoDS_Shape & shape, QList<TopoDS_Shape> & shapes, QList<TopoDS_Shape> & shapes2D)
    {
        if (shape.IsNull())
        {
            return;
        }

        TopAbs_ShapeEnum sType = shape.ShapeType();
        switch (sType)
        {
        case TopAbs_COMPOUND:
        case TopAbs_COMPSOLID:
        {
            // 遍历子形状。
            TopoDS_Iterator iter(shape);
            for (; iter.More(); iter.Next())
            {
                // 获取子形状递归拆分形状及信息。
                const TopoDS_Shape & subShape = iter.Value();
                FlattenCompShape2D(subShape, shapes, shapes2D);
            }

            break;
        }
        case TopAbs_SHELL:
        case TopAbs_FACE:
        {
            shapes2D.push_back(shape);
            break;
        }
        case TopAbs_SOLID:
        case TopAbs_WIRE:
        case TopAbs_EDGE:
        case TopAbs_VERTEX:
        {
            shapes.push_back(shape);
            break;
        }
        default:
            break;
        }
    }

    void FITKOCCComandCommon::FlattenCompShape3D(const TopoDS_Shape & shape, QList<TopoDS_Shape> & shapes, QList<TopoDS_Shape> & shapes3D)
    {
        if (shape.IsNull())
        {
            return;
        }

        TopAbs_ShapeEnum sType = shape.ShapeType();
        switch (sType)
        {
        case TopAbs_COMPOUND:
        case TopAbs_COMPSOLID:
        {
            // 遍历子形状。
            TopoDS_Iterator iter(shape);
            for (; iter.More(); iter.Next())
            {
                // 获取子形状递归拆分形状及信息。
                const TopoDS_Shape & subShape = iter.Value();
                FlattenCompShape3D(subShape, shapes, shapes3D);
            }

            break;
        }
        case TopAbs_SOLID:
        {
            shapes3D.push_back(shape);
            break;
        }
        case TopAbs_SHELL:
        case TopAbs_FACE:
        case TopAbs_WIRE:
        case TopAbs_EDGE:
        case TopAbs_VERTEX:
        {
            shapes.push_back(shape);
            break;
        }
        default:
            break;
        }
    }

    void FITKOCCComandCommon::FlattenCompShape2D3D(const TopoDS_Shape & shape, QList<TopoDS_Shape> & shapes,
        QList<TopoDS_Shape> & shapes2D, QList<TopoDS_Shape> & shapes3D)
    {
        if (shape.IsNull())
        {
            return;
        }

        TopAbs_ShapeEnum sType = shape.ShapeType();
        switch (sType)
        {
        case TopAbs_COMPOUND:
        case TopAbs_COMPSOLID:
        {
            // 遍历子形状。
            TopoDS_Iterator iter(shape);
            for (; iter.More(); iter.Next())
            {
                // 获取子形状递归拆分形状及信息。
                const TopoDS_Shape & subShape = iter.Value();
                FlattenCompShape2D3D(subShape, shapes, shapes2D, shapes3D);
            }

            break;
        }
        case TopAbs_SOLID:
        {
            shapes3D.push_back(shape);
            break;
        }
        case TopAbs_SHELL:
        case TopAbs_FACE:
        {
            shapes2D.push_back(shape);
            break;
        }
        case TopAbs_WIRE:
        case TopAbs_EDGE:
        case TopAbs_VERTEX:
        {
            shapes.push_back(shape);
            break;
        }
        default:
            break;
        }
    }

    void FITKOCCComandCommon::FlattenCompShapeBaseTopo(const TopoDS_Shape & shape, QList<TopoDS_Shape> & shapes, QList<TopoDS_Shape> & shapesBase)
    {
        if (shape.IsNull())
        {
            return;
        }

        TopAbs_ShapeEnum sType = shape.ShapeType();
        switch (sType)
        {
        case TopAbs_COMPOUND:
        case TopAbs_COMPSOLID:
        {
            // 遍历子形状。
            TopoDS_Iterator iter(shape);
            for (; iter.More(); iter.Next())
            {
                // 获取子形状递归拆分形状及信息。
                const TopoDS_Shape & subShape = iter.Value();
                FlattenCompShapeBaseTopo(subShape, shapes, shapesBase);
            }

            break;
        }
        case TopAbs_SOLID:
        case TopAbs_SHELL:
        {
            shapes.push_back(shape);
            break;
        }
        case TopAbs_FACE:
        case TopAbs_WIRE:
        case TopAbs_EDGE:
        case TopAbs_VERTEX:
        {
            shapesBase.push_back(shape);
            break;
        }
        default:
            break;
        }
    }

    void FITKOCCComandCommon::MakeWires(const TopoDS_Shape & shape, QList<TopoDS_Wire> & wires, double tol)
    {
        wires.clear();

        if (shape.IsNull())
        {
            return;
        }

        Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape;

        // 获取全部边
        int nEdges = 0;
        TopExp_Explorer exp(shape, TopAbs_ShapeEnum::TopAbs_EDGE);
        while (exp.More())
        {
            const TopoDS_Edge & edge = TopoDS::Edge(exp.Current());
            if (edge.IsNull())
            {
                continue;
            }

            // 保存边。
            edges->Append(edge);
            exp.Next();

            nEdges++;
        }

        if (nEdges == 0)
        {
            return;
        }

        try
        {
            Handle(TopTools_HSequenceOfShape) ws = new TopTools_HSequenceOfShape;
            ShapeAnalysis_FreeBounds::ConnectEdgesToWires(edges, tol, false, ws);
            int nWires = ws->Size();
            if (nWires == 0)
            {
                return;
            }

            for (int i = 1; i <= nWires; i++)
            {
                const TopoDS_Wire & wire = TopoDS::Wire(ws->Value(i));
                if (wire.IsNull())
                {
                    continue;
                }

                wires.push_back(wire);
            }
        }
        catch (...)
        {
            return;
        }
    }

    void FITKOCCComandCommon::MakeWires(const TopoDS_Shape & shape, QList<QList<TopoDS_Wire>> & wiresList, double tol)
    {
        wiresList.clear();

        if (shape.IsNull())
        {
            return;
        }

        QList<TopoDS_Wire> ws;
        MakeWires(shape, ws, tol);

        if (ws.isEmpty())
        {
            return;
        }

        // 根据包围盒分组。
        while (!ws.isEmpty())
        {
            const TopoDS_Wire & w = ws.takeFirst();

            Bnd_Box box;
            BRepBndLib::Add(w, box, false);

            gp_Pnt ptMax = box.CornerMax();
            gp_Pnt ptMin = box.CornerMin();

            int iList = -1;
            bool cantains = false;
            for (const QList<TopoDS_Wire> & wList : wiresList)
            {
                iList++;
                if (wList.isEmpty())
                {
                    continue;
                }

                // 先比较该分组最大包围盒。
                Bnd_Box boxGroupMax;
                BRepBndLib::Add(wList.first(), boxGroupMax, false);

                gp_Pnt ptFirstMax = boxGroupMax.CornerMax();
                gp_Pnt ptFirstMin = boxGroupMax.CornerMin();

                bool inGroup = false;
                if (ptMax.Coord(1) < ptFirstMax.Coord(1) &&
                    ptMax.Coord(2) < ptFirstMax.Coord(2) &&
                    ptMax.Coord(3) < ptFirstMax.Coord(3) &&
                    ptMin.Coord(1) > ptFirstMin.Coord(1) &&
                    ptMin.Coord(2) > ptFirstMin.Coord(2) &&
                    ptMin.Coord(3) > ptFirstMin.Coord(3))
                {
                    inGroup = true;
                }
                else if(ptMax.Coord(1) > ptFirstMax.Coord(1) &&
                    ptMax.Coord(2) > ptFirstMax.Coord(2) &&
                    ptMax.Coord(3) > ptFirstMax.Coord(3) &&
                    ptMin.Coord(1) < ptFirstMin.Coord(1) &&
                    ptMin.Coord(2) < ptFirstMin.Coord(2) &&
                    ptMin.Coord(3) < ptFirstMin.Coord(3))
                {
                    inGroup = true;
                }

                if (!inGroup)
                {
                    continue;
                }

                // 比较盒子。
                for (int i = 0; i < wList.count(); i++)
                {
                    // 从大到小排序。
                    Bnd_Box boxGroup;
                    BRepBndLib::Add(wList[i], boxGroup, false);

                    gp_Pnt ptGroupMax = boxGroup.CornerMax();
                    gp_Pnt ptGroupMin = boxGroup.CornerMin();

                    if (ptMax.Coord(1) > ptGroupMax.Coord(1) &&
                        ptMax.Coord(2) > ptGroupMax.Coord(2) &&
                        ptMax.Coord(3) > ptGroupMax.Coord(3) &&
                        ptMin.Coord(1) < ptGroupMin.Coord(1) &&
                        ptMin.Coord(2) < ptGroupMin.Coord(2) &&
                        ptMin.Coord(3) < ptGroupMin.Coord(3))
                    {
                        cantains = true;
                        wiresList[iList].insert(i, w);
                        break;
                    }
                }

                if (cantains)
                {
                    break;
                }

                if (inGroup)
                {
                    cantains = true;
                    wiresList[iList].push_back(w);
                    break;
                }
            }

            if (cantains)
            {
                continue;
            }

            QList<TopoDS_Wire> wGroup;
            wGroup.push_back(w);
            wiresList.push_back(wGroup);
        }
    }

    void FITKOCCComandCommon::MakeWires(const TopoDS_Shape & shape, TopoDS_Shape & wires, double tol)
    {
        QList<TopoDS_Wire> ws;
        MakeWires(shape, ws, tol);

        if (ws.isEmpty())
        {
            return;
        }

        TopoDS_Builder builder;
        TopoDS_Compound compound;
        builder.MakeCompound(compound);

        for (const TopoDS_Wire & wire : ws)
        {
            builder.Add(compound, wire);
        }

        wires = compound;
    }

    std::vector<TopoDS_Wire> FITKOCCComandCommon::bulidWire(std::list<TopoDS_Edge> &edgeList)
    {
        std::vector<TopoDS_Wire> wires;

        while (edgeList.size() > 0)
        {
            BRepBuilderAPI_MakeWire mkWire;
            mkWire.Add(edgeList.front());
            edgeList.pop_front();

            TopoDS_Wire new_wire = mkWire.Wire(); // current new wire

            bool found = false;
            do
            {
                found = false;
                for (std::list<TopoDS_Edge>::iterator pE = edgeList.begin(); pE != edgeList.end(); ++pE)
                {
                    mkWire.Add(*pE);
                    if (mkWire.Error() != BRepBuilderAPI_DisconnectedWire)
                    {
                        found = true;
                        edgeList.erase(pE);
                        new_wire = mkWire.Wire();
                        break;
                    }
                }
            } while (found);

            // Fix any topological issues of the wire
            ShapeFix_Wire aFix;
            aFix.SetPrecision(Precision::Confusion());
            aFix.Load(new_wire);
            aFix.FixReorder();
            aFix.FixConnected();
            aFix.FixClosed();
            wires.push_back(aFix.Wire());
        }

        return wires;
    }

    TopoDS_Shape FITKOCCComandCommon::makeFace(std::vector<TopoDS_Wire> &w)
    {
        if (w.empty())
            return TopoDS_Shape();

        std::vector<TopoDS_Wire> wires = w;
        std::sort(wires.begin(), wires.end(), Wire_Compare());
        std::list<TopoDS_Wire> wire_list;
        wire_list.insert(wire_list.begin(), wires.rbegin(), wires.rend());

        // separate the wires into several independent faces
        std::list<std::list<TopoDS_Wire>> sep_wire_list;
        while (!wire_list.empty())
        {
            std::list<TopoDS_Wire> sep_list;
            TopoDS_Wire wire = wire_list.front();
            wire_list.pop_front();
            sep_list.push_back(wire);

            std::list<TopoDS_Wire>::iterator it = wire_list.begin();
            while (it != wire_list.end())
            {
                if (isInside(wire, *it))
                {
                    sep_list.push_back(*it);
                    it = wire_list.erase(it);
                }
                else
                {
                    ++it;
                }
            }

            sep_wire_list.push_back(sep_list);
        }

        if (sep_wire_list.size() == 1)
        {
            std::list<TopoDS_Wire> &wires = sep_wire_list.front();
            return makeFace(wires);
        }
        else if (sep_wire_list.size() > 1)
        {
            TopoDS_Compound comp;
            BRep_Builder builder;
            builder.MakeCompound(comp);
            for (std::list<std::list<TopoDS_Wire>>::iterator it = sep_wire_list.begin(); it != sep_wire_list.end(); ++it)
            {
                TopoDS_Shape aFace = makeFace(*it);
                if (!aFace.IsNull())
                    builder.Add(comp, aFace);
            }
            if (comp.Closed() == false)
            {
                return TopoDS_Shape(); // no closed.
            }
            return comp;
        }
        else
        {
            return TopoDS_Shape(); // error
        }
    }

    TopoDS_Shape FITKOCCComandCommon::makeFace(std::list<TopoDS_Wire> &wires)
    {
        if (wires.size() < 1)
        {
            return TopoDS_Shape();
        }
        BRepBuilderAPI_MakeFace mkFace(wires.front());
        const TopoDS_Face &face = mkFace.Face();
        if (face.IsNull())
            return face;
        gp_Dir axis(0, 0, 1);
        BRepAdaptor_Surface adapt(face);
        if (adapt.GetType() == GeomAbs_Plane)
        {
            axis = adapt.Plane().Axis().Direction();
        }

        wires.pop_front();
        for (std::list<TopoDS_Wire>::iterator it = wires.begin(); it != wires.end(); ++it)
        {
            BRepBuilderAPI_MakeFace mkInnerFace(*it);
            const TopoDS_Face &inner_face = mkInnerFace.Face();
            if (inner_face.IsNull())
                return inner_face; // failure
            gp_Dir inner_axis(0, 0, 1);
            BRepAdaptor_Surface adapt(inner_face);
            if (adapt.GetType() == GeomAbs_Plane)
            {
                inner_axis = adapt.Plane().Axis().Direction();
            }
            // It seems that orientation is always 'Forward' and we only have to reverse
            // if the underlying plane have opposite normals.
            if (axis.Dot(inner_axis) < 0)
                it->Reverse();
            mkFace.Add(*it);
        }
        return validateFace(mkFace.Face());
    }

    bool FITKOCCComandCommon::isInside(const TopoDS_Wire &wire1, const TopoDS_Wire &wire2)
    {
        Bnd_Box box1;
        BRepBndLib::Add(wire1, box1);
        box1.SetGap(0.0);

        Bnd_Box box2;
        BRepBndLib::Add(wire2, box2);
        box2.SetGap(0.0);

        if (box1.IsOut(box2))
            return false;

        double prec = Precision::Confusion();
        prec = 1E-6;

        BRepBuilderAPI_MakeFace mkFace(wire1);
        if (!mkFace.IsDone())
            Standard_Failure::Raise("Failed to create a face from wire in sketch");
        TopoDS_Face face = validateFace(mkFace.Face());
        BRepAdaptor_Surface adapt(face);
        IntTools_FClass2d class2d(face, prec);
        Handle_Geom_Surface surf = new Geom_Plane(adapt.Plane());
        ShapeAnalysis_Surface as(surf);

        TopExp_Explorer xp(wire2, TopAbs_VERTEX);
        while (xp.More())
        {
            TopoDS_Vertex v = TopoDS::Vertex(xp.Current());
            gp_Pnt p = BRep_Tool::Pnt(v);
            gp_Pnt2d uv = as.ValueOfUV(p, prec);
            if (class2d.Perform(uv) == TopAbs_IN)
                return true;
            // TODO: We can make a check to see if all points are inside or all outside
            // because otherwise we have some intersections which is not allowed
            else
                return false;
            xp.Next();
        }

        return false;
    }

    TopoDS_Face FITKOCCComandCommon::validateFace(const TopoDS_Face &face)
    {
        BRepCheck_Analyzer aChecker(face);
        if (!aChecker.IsValid())
        {
            TopoDS_Wire outerwire = ShapeAnalysis::OuterWire(face);
            TopTools_IndexedMapOfShape myMap;
            myMap.Add(outerwire);

            TopExp_Explorer xp(face, TopAbs_WIRE);
            ShapeFix_Wire fix;
            fix.SetFace(face);
            fix.Load(outerwire);
            fix.Perform();
            BRepBuilderAPI_MakeFace mkFace(fix.WireAPIMake());
            while (xp.More())
            {
                if (!myMap.Contains(xp.Current()))
                {
                    fix.Load(TopoDS::Wire(xp.Current()));
                    fix.Perform();
                    mkFace.Add(fix.WireAPIMake());
                }
                xp.Next();
            }

            aChecker.Init(mkFace.Face());
            if (!aChecker.IsValid())
            {
                ShapeFix_Shape fix(mkFace.Face());
                fix.SetPrecision(Precision::Confusion());
                fix.SetMaxTolerance(Precision::Confusion());
                fix.SetMaxTolerance(Precision::Confusion());
                fix.Perform();
                fix.FixWireTool()->Perform();
                fix.FixFaceTool()->Perform();
                TopoDS_Face fixedFace = TopoDS::Face(fix.Shape());
                aChecker.Init(fixedFace);
                if (!aChecker.IsValid())
                    return TopoDS_Face();
                // Standard_Failure::Raise("Failed to validate broken face");
                return fixedFace;
            }
            return mkFace.Face();
        }

        return face;
    }

    TopoDS_Shape FITKOCCComandCommon::removeSplitter(const TopoDS_Shape &shape)
    {
        if (shape.IsNull())
            Standard_Failure::Raise("Cannot remove splitter from empty shape");

        if (shape.ShapeType() == TopAbs_SOLID)
        {
            const TopoDS_Solid &solid = TopoDS::Solid(shape);
            BRepBuilderAPI_MakeSolid mkSolid;
            TopExp_Explorer it;
            for (it.Init(solid, TopAbs_SHELL); it.More(); it.Next())
            {
                const TopoDS_Shell &currentShell = TopoDS::Shell(it.Current());
                ModelRefine::FaceUniter uniter(currentShell);
                if (uniter.process())
                {
                    if (uniter.isModified())
                    {
                        const TopoDS_Shell &newShell = uniter.getShell();
                        mkSolid.Add(newShell);
                    }
                    else
                    {
                        mkSolid.Add(currentShell);
                    }
                }
                else
                {
                    Standard_Failure::Raise("Removing splitter failed");
                    return shape;
                }
            }
            return mkSolid.Solid();
        }
        else if (shape.ShapeType() == TopAbs_SHELL)
        {
            const TopoDS_Shell &shell = TopoDS::Shell(shape);
            ModelRefine::FaceUniter uniter(shell);
            if (uniter.process())
            {
                return uniter.getShell();
            }
            else
            {
                Standard_Failure::Raise("Removing splitter failed");
            }
        }
        else if (shape.ShapeType() == TopAbs_COMPOUND)
        {
            BRep_Builder builder;
            TopoDS_Compound comp;
            builder.MakeCompound(comp);

            TopExp_Explorer xp;
            // solids
            for (xp.Init(shape, TopAbs_SOLID); xp.More(); xp.Next())
            {
                const TopoDS_Solid &solid = TopoDS::Solid(xp.Current());
                BRepTools_ReShape reshape;
                TopExp_Explorer it;
                for (it.Init(solid, TopAbs_SHELL); it.More(); it.Next())
                {
                    const TopoDS_Shell &currentShell = TopoDS::Shell(it.Current());
                    ModelRefine::FaceUniter uniter(currentShell);
                    if (uniter.process())
                    {
                        if (uniter.isModified())
                        {
                            const TopoDS_Shell &newShell = uniter.getShell();
                            reshape.Replace(currentShell, newShell);
                        }
                    }
                }
                builder.Add(comp, reshape.Apply(solid));
            }
            // free shells
            for (xp.Init(shape, TopAbs_SHELL, TopAbs_SOLID); xp.More(); xp.Next())
            {
                const TopoDS_Shell &shell = TopoDS::Shell(xp.Current());
                ModelRefine::FaceUniter uniter(shell);
                if (uniter.process())
                {
                    builder.Add(comp, uniter.getShell());
                }
            }
            // the rest
            for (xp.Init(shape, TopAbs_FACE, TopAbs_SHELL); xp.More(); xp.Next())
            {
                if (!xp.Current().IsNull())
                    builder.Add(comp, xp.Current());
            }
            for (xp.Init(shape, TopAbs_WIRE, TopAbs_FACE); xp.More(); xp.Next())
            {
                if (!xp.Current().IsNull())
                    builder.Add(comp, xp.Current());
            }
            for (xp.Init(shape, TopAbs_EDGE, TopAbs_WIRE); xp.More(); xp.Next())
            {
                if (!xp.Current().IsNull())
                    builder.Add(comp, xp.Current());
            }
            for (xp.Init(shape, TopAbs_VERTEX, TopAbs_EDGE); xp.More(); xp.Next())
            {
                if (!xp.Current().IsNull())
                    builder.Add(comp, xp.Current());
            }

            return comp;
        }

        return shape;
    }

    bool FITKOCCComandCommon::isEmpty(const TopoDS_Shape &shape)
    {
        TopExp_Explorer ptExp(shape, TopAbs_VERTEX);
        for (; ptExp.More(); ptExp.Next())
            return false;

        TopExp_Explorer edgeExp(shape, TopAbs_EDGE);
        for (; edgeExp.More(); edgeExp.Next())
            return false;

        TopExp_Explorer faceExp(shape, TopAbs_FACE);
        for (; faceExp.More(); faceExp.Next())
            return false;

        return true;
    }

    TopoDS_Shape FITKOCCComandCommon::removeShape(TopoDS_Shape *inputShape, TopoDS_Shape *component)
    {

        TopoDS_Shape copyshape = BRepBuilderAPI_Copy(*inputShape);

        Handle(TopoDS_TShape) hand1 = inputShape->TShape();
        Handle(TopoDS_TShape) hand2 = component->TShape();
        if (hand1 == hand2)
        {
            *inputShape = TopoDS_Shape();
            return copyshape;
        }
        const TopoDS_Shape &aCuttedShape = BRepAlgoAPI_Cut(*inputShape, *component);
        *inputShape = aCuttedShape;
        //      BRep_Builder builder;
        //      builder.Remove(*inputShape, *component);
        return copyshape;
    }

    /*
        gp_Ax2 FITKOCCComandCommon::getEdgeAxis(Geometry::GeometrySet* set, int edgeindex)
        {
            TopoDS_Shape* shape = set->getShape();
            TopExp_Explorer edgeExp(*shape, TopAbs_EDGE);
            for (int index = 0; index < edgeindex && edgeExp.More(); edgeExp.Next(), ++index);

            const TopoDS_Shape& edgeShape = edgeExp.Current();
            if (edgeShape.IsNull()) return;
            const TopoDS_Edge &edgeone = TopoDS::Edge(edgeShape);
            if (edgeone.IsNull()) return;


            Standard_Real first, last;
            Handle(Geom_Curve) &curve = BRep_Tool::Curve(edgeone, first, last);
            Handle(Geom_TrimmedCurve) myTrimmed = new Geom_TrimmedCurve(curve, first, last);
            Handle(Geom_BSplineCurve) NurbsCurve = GeomConvert::CurveToBSplineCurve(myTrimmed);

            GeomAdaptor_Curve GAC(NurbsCurve);
            GCPnts_UniformAbscissa UA(GAC, 200);
            if (!UA.IsDone()) return;
            Standard_Real n = UA.NbPoints();
            for (int i = 0; i < n; ++i)
            {
                Standard_Real parami = UA.Parameter(i + 1);
                gp_Pnt tpnt;
                gp_Vec vpnt;
                curve->D1(parami, tpnt, vpnt);
            }
        }*/
        /*
        gp_Ax2 FITKOCCComandCommon::getFaceAxis(Geometry::GeometrySet* set, int index)
        {
            return gp_Ax2;
        }*/

}